﻿using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
using System.Collections;
using System.Collections.Generic;

public class EditScriptWindow : EditorWindow
{
	private bool scriptModified = false;
	private string scriptPath;
	private string scriptText;
	private Vector2 scroll;
	private MonoScript script;

	public void InitScript(MonoScript _script)
	{
		script = _script;
		scriptPath = AssetDatabase.GetAssetPath(_script);
		ReadText(scriptPath);
	}

	private void ReadText(string _path)
	{
		scriptModified = false;
		scriptText = File.ReadAllText(_path);
	}

	private void WriteText(string _path)
	{
		scriptModified = false;

		bool windowsLineFeed = false;
		int firstLineFeed = scriptText.IndexOf('\n');
		if (firstLineFeed > 0 && scriptText[firstLineFeed - 1] == '\r')
		{
			windowsLineFeed = true;
		}

		if (windowsLineFeed)
		{
			scriptText = AddCR(scriptText);
		}
		else
		{
			scriptText = RemoveCR(scriptText);
		}

		string path = Application.dataPath.Remove(Application.dataPath.LastIndexOf("/")) + "/" + _path;
		File.WriteAllText(path, scriptText);
		AssetDatabase.Refresh();
	}

	private string AddCR(string _text)
	{
		bool solved = false;
		while (!solved)
		{
			solved = true;
			for (int i = 0; i < _text.Length; i++)
			{
				if (_text[i] == '\n')
				{
					if (i == 0 || _text[i - 1] != '\r')
					{
						_text = InsertText(_text, i, "\r");
						solved = false;
						break;
					}
				}
				else if (_text[i] == '\r')
				{
					if (i == _text.Length - 1 || _text[i + 1] != '\n')
					{
						_text = RemoveText(_text, i);
						solved = false;
						break;
					}
				}
			}
		}

		return _text;
	}

	private string RemoveCR(string _text)
	{
		bool solved = false;
		while (!solved)
		{
			solved = true;
			for (int i = 0; i < _text.Length; i++)
			{
				if (_text[i] == '\n')
				{
					if (i > 0 && _text[i - 1] == '\r')
					{
						_text = RemoveText(_text, i - 1);
						solved = false;
						break;
					}
				}
				else if (_text[i] == '\r')
				{
					if (i == _text.Length - 1 || _text[i + 1] != '\n')
					{
						_text = RemoveText(_text, i - 1);
						_text = InsertText(_text, i - 1, "\n");
						solved = false;
						break;
					}
				}
			}
		}

		return _text;
	}

	private string InsertText(string _original, int _index, string _toInsert)
	{
		return _original.Substring(0, Mathf.Max(_index, 0)) + _toInsert + _original.Substring(Mathf.Min(_index, _original.Length - 1));
	}

	private string RemoveText(string _original, int _index)
	{
		return _original.Substring(0, Mathf.Max(_index, 0)) + _original.Substring(Mathf.Min(_index + 1, _original.Length - 1));
	}

	private void OnGUI()
	{
		EditorGUILayout.BeginHorizontal();
		{
			GUILayout.Label(scriptPath + (scriptModified ? "***" : ""), EditorStyles.largeLabel);
		}
		EditorGUILayout.EndHorizontal();

		EditorGUILayout.BeginHorizontal();
		{
			GUILayout.FlexibleSpace();
			GUILayout.Label("Open : ");
			MonoScript newScript = (MonoScript)EditorGUILayout.ObjectField(script, typeof(MonoScript), false);
			if (newScript != script)
			{
				InitScript(newScript);
				return;
			}
			if (GUILayout.Button("Save", GUILayout.Width(100f)))
			{
				WriteText(scriptPath);
			}
			if (GUILayout.Button("Reload", GUILayout.Width(100f)))
			{
				ReadText(scriptPath);
			}
		}
		EditorGUILayout.EndHorizontal();

		if (!ReferenceEquals(scriptPath, null))
		{
			scroll = EditorGUILayout.BeginScrollView(scroll, "box");
			{
				int nbLines = scriptText.Count(x => x == '\n') + 1;
				float height = nbLines * 13.2f;
				height = height < Screen.height - 100f ? Screen.height - 100f : height;
				string text = EditorGUILayout.TextArea(scriptText, EditorStyles.textField, GUILayout.Height(height));
				if (text != scriptText)
				{
					scriptModified = true;
					scriptText = text;
				}
			}
			EditorGUILayout.EndScrollView();
		}
	}
}
